﻿using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using SHKF.B2C.MeiTuanPeiSong.Model.Dto;
using SHKF.B2C.MeiTuanPeiSong.Model.Dto.Order;
using SHKF.B2C.MeiTuanPeiSong.Model.Dto.Order.Check;
using SHKF.B2C.MeiTuanPeiSong.Model.Dto.Order.Pre;
using SHKF.B2C.MeiTuanPeiSong.Model.Dto.Order.RiderLocation;
using SHKF.B2C.MeiTuanPeiSong.Model.Dto.Shop;
using SHKF.B2C.MeiTuanPeiSong.Model.Dto.ShopArea;
using SHKF.B2C.MeiTuanPeiSong.Model.Request;
using SHKF.B2C.MeiTuanPeiSong.Model.Request.Test;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
 

namespace SHKF.B2C.MeiTuanPeiSong.Network
{
    public class HttpClientMeiTuanPeiSong : HttpClient
    {
        private string urlOrderCheck = "/order/check"; //订单创建（门店方式）
        private string urlOrderCreateByShop = "/order/createByShop"; //订单创建（门店方式）
        private string urlOrderPreCreateByShop = "/order/preCreateByShop"; //订单创建（门店方式）
        private string urlOrderQuery = "/order/status/query"; //查询订单状态
        private string urlOrderDelete = "/order/delete";

        private string urlShopQuery = "/shop/query";
        private string urlShopAreaQuery = "/shop/area/query";   //查询门店配送范围


        private string urlTestShopStatus = "/test/shop/status/callback";  //门店状态回调测试
       
        private readonly ILogger<HttpClientMeiTuanPeiSong> logger;

        public HttpClientMeiTuanPeiSong(ILogger<HttpClientMeiTuanPeiSong> logger)
        {
            base.BaseAddress = new Uri("https://peisongopen.meituan.com/api"); 
            this.logger = logger;
        }

        #region 门店

        /// <summary>
        /// 获取门店信息
        /// </summary>
        /// <param name="shopID"></param>
        /// <returns></returns>
        public async Task<ShopDtoV2> ShopQuery(string shopID)
        {
            ShopDtoV2 dto = new ShopDtoV2();
            try
            {
                ShopQueryRequest request = new ShopQueryRequest();
                request.shop_id = shopID;
                HttpResponseMessage httpResponseMessage = await this.PostAsync(urlShopQuery, request);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<ShopDtoV2>();
                }
                else
                {
                    dto.code = -1;
                    dto.message = httpResponseMessage.ToString();

                    this.WriteInformation("ShopQuery", $"message:{dto.message }");
                }
            }
            catch (Exception ex)
            {
                this.WriteException("ShopQuery", ex);
            }
            return dto;
        }

        /// <summary>
        /// 查询门店配送范围
        /// </summary>
        /// <param name="delivery_service_code"></param>
        /// <param name="shop_id"></param>
        /// <returns></returns>
        public async Task<MtpsShopAreaDto> ShopAreaQuery(int delivery_service_code, string shop_id)
        {
            MtpsShopAreaDto dto = new MtpsShopAreaDto();
            try
            {
                ShopAreaQueryRequest request = new ShopAreaQueryRequest();
                request.shop_id = shop_id;
                request.delivery_service_code = delivery_service_code;

                HttpResponseMessage httpResponseMessage = await this.PostAsync(urlShopAreaQuery, request);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    string result = await httpResponseMessage.Content.ReadAsStringAsync();
                    result = result.Replace("\\\"", "").Replace("\"","");
                    dto = JsonConvert.DeserializeObject< MtpsShopAreaDto>(result);

                    //dto = await httpResponseMessage.Content.ReadAsAsync<MtpsShopAreaDto>();
                }
                else
                {
                    dto.code = -1;
                    dto.message = httpResponseMessage.ToString();

                    this.WriteInformation("ShopQuery", $"message:{dto.message }");
                }
            }
            catch (Exception ex)
            {
                this.WriteException("ShopQuery", ex);
            }
            return dto;
        }

        #endregion

        #region 定单

        /// <summary>
        /// 配送能力校验
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<OrderCheckDto> OrderCheck(OrderCheckRequest request)
        {
            OrderCheckDto dto = new OrderCheckDto();
            try
            {
                HttpResponseMessage httpResponseMessage = await this.PostAsync(urlOrderCheck, request);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<OrderCheckDto>();
                }
                else
                {
                    dto.code = -1;
                    dto.message = httpResponseMessage.ToString();

                    this.WriteInformation("OrderCheck", $"message:{dto.message }");
                }

            }
            catch (Exception ex)
            {
                this.WriteException("OrderCheck", ex);
            }
            return dto;
        }

        /// <summary>
        /// 订单创建（门店方式）
        /// </summary>
        /// <param name="createOrderByShop"></param>
        /// <returns></returns>
        public async Task<OrderDto> OrderCreateByShop(CreateOrderByShopRequest createOrderByShop)
        {
            OrderDto dto = new OrderDto();
            try
            {
                HttpResponseMessage httpResponseMessage = await this.PostAsync(urlOrderCreateByShop, createOrderByShop);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<OrderDto>();
                }
                else
                {
                    dto.code = -1;
                    dto.message = httpResponseMessage.ToString();

                    this.WriteInformation("OrderCreateByShop", $"message:{dto.message }");
                }

            }
            catch (Exception ex)
            {
                this.WriteException("OrderCreateByShop", ex);
            }
            return dto;
        }

        /// <summary>
        /// 预发单接口
        /// </summary>
        /// <param name="createOrderByShop"></param>
        /// <returns></returns>
        public async Task<PreOrderDto> OrderPreCreateByShop(CreateOrderByShopRequest createOrderByShop)
        {
            PreOrderDto dto = new PreOrderDto();
            try
            {
                HttpResponseMessage httpResponseMessage = await this.PostAsync(urlOrderPreCreateByShop, createOrderByShop);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<PreOrderDto>();
                }
                else
                {
                    dto.code = -1;
                    dto.message = httpResponseMessage.ToString();

                    this.WriteInformation("OrderPreCreateByShop", $"message:{dto.message }");
                }

            }
            catch (Exception ex)
            {
                this.WriteException("OrderPreCreateByShop", ex);
            }
            return dto;
        }

        /// <summary>
        /// 定单状态查询
        /// </summary>
        /// <param name="queryStatusRequest"></param>
        /// <returns></returns>
        public async Task<OrderStatusDto> QueryStatus(QueryStatusRequest queryStatusRequest)
        {
            OrderStatusDto dto = new OrderStatusDto();
            try
            {
                HttpResponseMessage httpResponseMessage = await this.PostAsync(urlOrderQuery, queryStatusRequest);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<OrderStatusDto>();
                }
                else
                {
                    dto.code = -1;
                    dto.message = httpResponseMessage.ToString();

                    this.WriteInformation("OrderCreateByShop", $"message:{dto.message }");
                }

            }
            catch (Exception ex)
            {
                this.WriteException("QueryStatus", ex);
            }
            return dto;
        }

        /// <summary>
        /// 取消定单
        /// </summary>
        /// <param name="orderRequest"></param>
        /// <returns></returns>
        public async Task<OrderDeleteDto> OrderDetele(CancelOrderRequest orderRequest)
        {
            OrderDeleteDto dto = new OrderDeleteDto();
            try
            {
                HttpResponseMessage httpResponseMessage = await this.PostAsync(urlOrderDelete, orderRequest);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<OrderDeleteDto>();
                }
                else
                {
                    dto.code = -1;
                    dto.message = httpResponseMessage.ToString();

                    this.WriteInformation("OrderCreateByShop", $"message:{dto.message }");
                }
            }
            catch (Exception ex)
            {
                this.WriteException("OrderCreateByShop", ex);
            }
            return dto;
        }

        /// <summary>
        /// 获取配送码
        /// </summary>
        /// <param name="shop_id"></param>
        /// <param name="order_id"></param>
        /// <returns></returns>
        public async Task<DeliveryCodeDto2> CreateDeliveryCode(string shop_id, string order_id)
        {
            DeliveryCodeDto2 dto = new DeliveryCodeDto2();

            try
            {
                DeliveryCodeRequest request = new DeliveryCodeRequest();
                request.shop_id = shop_id;
                request.order_id = order_id;
                HttpResponseMessage httpResponseMessage = await this.PostAsync(urlShopQuery, request);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<DeliveryCodeDto2>();
                }
                else
                {
                    dto.code = -1;
                    dto.message = httpResponseMessage.ToString();

                    this.WriteInformation("CreateDeliveryCode", $"message:{dto.message }");
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return dto;
        }

        /// <summary>
        /// 获取骑手当前位置
        /// </summary>
        /// <param name="delivery_id"></param>
        /// <param name="mt_peisong_id"></param>
        /// <returns></returns>
        public async Task<MtpsRiderLocationDto> OrderRiderLocation(long delivery_id, string mt_peisong_id)
        {
            MtpsRiderLocationDto dto = new MtpsRiderLocationDto();

            try
            {
                RiderLocationRequest request = new RiderLocationRequest();
                request.delivery_id = delivery_id;
                request.mt_peisong_id = mt_peisong_id;

                HttpResponseMessage httpResponseMessage = await this.PostAsync("/order/rider/location", request);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<MtpsRiderLocationDto>();
                }
                else
                {
                    dto.code = -1;
                    dto.message = httpResponseMessage.ToString();

                    this.WriteInformation("OrderRiderLocation", $"message:{dto.message }");
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return dto;
        }

        #endregion

        #region 测试

        /// <summary>
        /// 门店状态回调测试
        /// </summary>
        /// <param name="shop_id"></param>
        /// <param name="status"></param>
        /// <returns></returns>
        public async Task<CodeDto> TestShopStatusCallback(string shop_id, int status)
        {
            CodeDto dto = new CodeDto();
            try
            {
                TestShopStatusRequest request = new TestShopStatusRequest();
                request.shop_id = shop_id;
                request.status = status;
                HttpResponseMessage httpResponseMessage = await this.PostAsync(urlTestShopStatus, request);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<MessageDto>();
                }
                else
                {
                    dto.code = -1;
                    string msg = httpResponseMessage.ToString(); 
                    this.WriteInformation("ShopQuery", $"message:{msg }");
                }
            }
            catch (Exception ex)
            {
                this.WriteException("ShopStatusCallback", ex);
            }
            return dto;
        }

        /// <summary>
        /// 模拟接单
        /// </summary>
        /// <param name="delivery_id"></param>
        /// <param name="mt_peisong_id"></param>
        /// <returns></returns>
        public async Task<MessageDto> TestOrderArrange(long delivery_id, string mt_peisong_id)
        {
            MessageDto dto = new MessageDto();
            try
            {
                TestQiShouRequest request = new TestQiShouRequest();
                request.delivery_id = delivery_id;
                request.mt_peisong_id = mt_peisong_id;
                HttpResponseMessage httpResponseMessage = await this.PostAsync("/test/order/arrange", request);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<MessageDto>();
                }
                else
                {
                    dto.code = -1;
                    string msg = httpResponseMessage.ToString();
                    this.WriteInformation("TestOrderArrange", $"message:{msg }");
                }
            }
            catch (Exception ex)
            {
                this.WriteException("TestOrderArrange", ex);
            }
            return dto;
        }

        /// <summary>
        /// 模拟取货
        /// </summary>
        /// <param name="delivery_id"></param>
        /// <param name="mt_peisong_id"></param>
        /// <returns></returns>
        public async Task<MessageDto> TestOrderPickup(long delivery_id, string mt_peisong_id)
        {
            MessageDto dto = new MessageDto();
            try
            {
                TestQiShouRequest request = new TestQiShouRequest();
                request.delivery_id = delivery_id;
                request.mt_peisong_id = mt_peisong_id;
                HttpResponseMessage httpResponseMessage = await this.PostAsync("/test/order/pickup", request);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<MessageDto>();
                }
                else
                {
                    dto.code = -1;
                    string msg = httpResponseMessage.ToString();
                    this.WriteInformation("TestOrderArrange", $"message:{msg }");
                }
            }
            catch (Exception ex)
            {
                this.WriteException("TestOrderArrange", ex);
            }
            return dto;
        }


        /// <summary>
        /// 模拟送达
        /// </summary>
        /// <param name="delivery_id"></param>
        /// <param name="mt_peisong_id"></param>
        /// <returns></returns>
        public async Task<MessageDto> TestOrderDeliver(long delivery_id, string mt_peisong_id)
        {
            MessageDto dto = new MessageDto();
            try
            {
                TestQiShouRequest request = new TestQiShouRequest();
                request.delivery_id = delivery_id;
                request.mt_peisong_id = mt_peisong_id;
                HttpResponseMessage httpResponseMessage = await this.PostAsync("/test/order/deliver", request);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<MessageDto>();
                }
                else
                {
                    dto.code = -1;
                    string msg = httpResponseMessage.ToString();
                    this.WriteInformation("TestOrderArrange", $"message:{msg }");
                }
            }
            catch (Exception ex)
            {
                this.WriteException("TestOrderArrange", ex);
            }
            return dto;
        }

        /// <summary>
        /// 模拟改派
        /// </summary>
        /// <param name="delivery_id"></param>
        /// <param name="mt_peisong_id"></param>
        /// <returns></returns>
        public async Task<MessageDto> TestOrderRearrange(long delivery_id, string mt_peisong_id)
        {
            MessageDto dto = new MessageDto();
            try
            {
                TestQiShouRequest request = new TestQiShouRequest();
                request.delivery_id = delivery_id;
                request.mt_peisong_id = mt_peisong_id;
                HttpResponseMessage httpResponseMessage = await this.PostAsync("/test/order/rearrange", request);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<MessageDto>();
                }
                else
                {
                    dto.code = -1;
                    string msg = httpResponseMessage.ToString();
                    this.WriteInformation("TestOrderArrange", $"message:{msg }");
                }
            }
            catch (Exception ex)
            {
                this.WriteException("TestOrderArrange", ex);
            }
            return dto;
        }

        /// <summary>
        /// 模拟上传异常
        /// </summary>
        /// <param name="delivery_id"></param>
        /// <param name="mt_peisong_id"></param>
        /// <returns></returns>
        public async Task<MessageDto> TestOrderReportException(long delivery_id, string mt_peisong_id)
        {
            MessageDto dto = new MessageDto();
            try
            {
                TestQiShouRequest request = new TestQiShouRequest();
                request.delivery_id = delivery_id;
                request.mt_peisong_id = mt_peisong_id;
                HttpResponseMessage httpResponseMessage = await this.PostAsync("/test/order/reportException", request);
                if (httpResponseMessage.IsSuccessStatusCode)
                {
                    dto = await httpResponseMessage.Content.ReadAsAsync<MessageDto>();
                }
                else
                {
                    dto.code = -1;
                    string msg = httpResponseMessage.ToString();
                    this.WriteInformation("TestOrderArrange", $"message:{msg }");
                }
            }
            catch (Exception ex)
            {
                this.WriteException("TestOrderArrange", ex);
            }
            return dto;
        }



        #endregion

        private async Task<HttpResponseMessage> PostAsync(string requestUri, AbstractRequest request)
        {
            String secret = OpenApiConfig.SECRET; 
            Dictionary<string, string> paramList = ParamBuilder.buildParams(request);
            String sign = SignHelper.generateSign(paramList, secret);
            paramList["sign"] = sign; 
            request.sign = sign; 

            var content = new FormUrlEncodedContent(paramList); 
            content.Headers.ContentType.CharSet = "utf-8";

            string url = base.BaseAddress.OriginalString + requestUri; 
            HttpResponseMessage httpResponseMessage = await base.PostAsync(url, content); 

            return httpResponseMessage;
        }
         
        protected void WriteException(string fun, Exception ex)
        {
            if (this.logger != null)
            {
                this.logger.LogError($"fun:{fun}>> ex:{ex.InnerException.Message}");
            }

        }

        protected void WriteInformation(string fun, string msg)
        {
            if (this.logger != null)
            {
                this.logger.LogInformation($"fun:{fun}>> msg:{msg}");
            }
        }

    }
}
